package king.dominic.jlibrary.database;

import android.database.sqlite.SQLiteDatabase;
import android.util.SparseArray;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
 * Created by Administrator on 2017/10/30.
 * TableFactory
 */

public class TableFactory {
    public static final String ID = "identity";
    private final SparseArray<HashMap<String, String>> mVersionParams = new SparseArray<>();
    private HashMap<String, String> mCurrentParams;
    private String table;
    private String mCurrentParameter;
    int mLastVersion = 0;

    public TableFactory(String table) {
        this.table = table;
    }

    public TableFactory addAutoincrementPrimaryKey() {
        exist(ID);
        mCurrentParams.put(ID, "INTEGER PRIMARY KEY AUTOINCREMENT");
        return this;
    }

    public TableFactory setVersionCode(int version) {
        if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);

        mLastVersion = version;
        mCurrentParams = new HashMap<>();
        mVersionParams.append(version, mCurrentParams);
        return this;
    }

    /**
     * 唯一
     *
     * @return TableFactory
     */
    public TableFactory primaryKey() {
        final String parameter = mCurrentParameter;
        String value = mCurrentParams.get(parameter);
        if (value != null) {
            mCurrentParams.put(parameter, value + " PRIMARY KEY");
            return this;
        }
        throw new IllegalArgumentException();
    }

    /**
     * 自增
     *
     * @return TableFactory
     */
    public TableFactory autoincrement() {
        final String parameter = mCurrentParameter;
        String value = mCurrentParams.get(parameter);
        if (value != null && value.contains("INTEGER") && value.contains("PRIMARY KEY")) {
            mCurrentParams.put(parameter, value + " AUTOINCREMENT");
            return this;
        }
        throw new IllegalArgumentException();
    }

    public TableFactory addText(String parameter) {
        exist(parameter);
        mCurrentParams.put(parameter, "TEXT");
        mCurrentParameter = parameter;
        return this;
    }

    public TableFactory addFloat(String parameter) {
        exist(parameter);
        mCurrentParams.put(parameter, "FLOAT");
        mCurrentParameter = parameter;
        return this;
    }

    public TableFactory addInteger(String parameter) {
        exist(parameter);
        mCurrentParams.put(parameter, "INTEGER");
        mCurrentParameter = parameter;
        return this;
    }

    void create(SQLiteDatabase db) {
        StringBuilder builder = new StringBuilder();
        builder.append("CREATE TABLE ")
                .append(table)
                .append("(");
        final int length = mVersionParams.size();
        for (int i = 0; i <= length; i++) {
            HashMap<String, String> params = mVersionParams.valueAt(i);
            Set<String> keys = params.keySet();
            for (String k : keys) {
                builder.append(k);
                builder.append(" ");
                builder.append(params.get(k));
                builder.append(",");
            }
        }
        builder.deleteCharAt(builder.length() - 1);
        builder.append(")");

        db.execSQL(builder.toString());
    }

    void upgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (newVersion <= oldVersion || mLastVersion <= oldVersion) return;

        StringBuilder builder = new StringBuilder();
        builder.append("ALTER TABLE ")
                .append(table)
                .append("ADD COLUMN ");

        final int length = mVersionParams.size();
        for (int i = 0; i <= length; i++) {
            int version = mVersionParams.keyAt(i);
            if (version > oldVersion) {
                HashMap<String, String> params = mVersionParams.get(version);
                Set<String> keys = params.keySet();
                for (String k : keys) {
                    builder.append(k);
                    builder.append(" ");
                    builder.append(params.get(k));
                    builder.append(",");
                }
            }
        }

        builder.deleteCharAt(builder.length() - 1);
        db.execSQL(builder.toString());
    }

    private void exist(String parameter) {
        if (mLastVersion == 0)
            throw new IllegalArgumentException("Unset version!");
        if (mCurrentParams.containsKey(parameter))
            throw new IllegalArgumentException();
    }

    public static class Table<Bean> {
        private final Class<Bean> clazz;

        public Table(Class<Bean> clazz) {
            king.dominic.jlibrary.database.Table annotation = clazz.getAnnotation(king.dominic.jlibrary.database.Table.class);
            if (annotation == null)
                throw new IllegalArgumentException("Class unset annotation: @Table(version = int)");

            this.clazz = clazz;

            List<Field> fields = Arrays.asList(clazz.getDeclaredFields());
            fields.addAll(Arrays.asList(clazz.getFields()));
            for(Field field:fields){
                field.setAccessible(true);
                String name = field.getName();
                Annotation[] as = field.getAnnotations();
                // TODO: 2017/11/1 数据库 - 表创建 - Table<Bean>
            }
        }
    }
}
